package com.yvan.spring.autoconfig;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yvan.cache.YvanRedisCacheManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.nio.charset.Charset;

@Configuration
@EnableCaching
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisCacheAutoConfiguration {

    private static final ObjectMapper OM;

    static {
        OM = new ObjectMapper();
        OM.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        OM.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        OM.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //OM.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        //OM.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
    }

    @Value("${spring.cache.expire-time-seconds}")
    public long CacheExpireTimeOfSeconds = 300;

    @Bean
    public CacheManager cacheManager(@Qualifier("secondaryStringRedisTemplate") RedisTemplate redisTemplate) {
        //RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate);
        YvanRedisCacheManager redisCacheManager = new YvanRedisCacheManager(redisTemplate);
        redisCacheManager.setDefaultExpiration(CacheExpireTimeOfSeconds);
        redisCacheManager.setUsePrefix(true);
        return redisCacheManager;
    }

    @SuppressWarnings("unchecked")
    @Bean(name = "secondaryStringRedisTemplate")
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        //GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer(OM);
        //template.setValueSerializer(serializer);

        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
        serializer.setObjectMapper(OM);
        template.setValueSerializer(serializer);

        template.setKeySerializer(new StringRedisSerializer(Charset.forName("UTF-8")));
        template.afterPropertiesSet();

        return template;
    }
}
